#pragma once

#include "structures.h"

class Helper;
class Face;
class FaceFactory;
class Triangle;
class CFigure2D;
//extern class CgalTriangulation;
class CGTriangulate;
struct figureVertice;
struct figureEdge;
enum   verticeType;
//The class is responsible to split convex into many monotone faces
//which can be easy afterthat triangulated
//The main structure which is output of this 
//class (and a part of) is a Face
//Face represented a monotony figure based on the dobly-side edge list

typedef std::list<long long> figPoints; //we fake the std and treat the pointers as long long value :)
typedef figPoints::iterator  figPointsIterator;

//typedef std::priority_queue<figureVertice *, std::vector<figureVertice *>, std::less<std::vector<figureVertice *>::value_type>> vertQueue;
//The queue above based on long int (pointer) and doesn't execute the operator < or >
//typedef std::priority_queue<figureVertice, std::vector<figureVertice>, std::less<std::vector<figureVertice>::value_type>> vertQueue;
typedef std::priority_queue<figureVertice, std::vector<figureVertice>> vertQueue;

typedef std::list<long long> edgeList;
typedef edgeList::iterator   edgeIterator;

//typedef std::list<figureEdge, std::less<std::vector<figureEdge>::value_type>>  diagonalList;
typedef std::set<figureEdge, std::less<std::vector<figureEdge>::value_type>>  diagonalList; //sorted list basedon x-coordinate
typedef diagonalList::iterator diagonalListIterator;


//type for searching where the key is a diagonal and value is an edge which has to be removed
typedef std::multimap<figureEdge, long long>         diagonalMap;
typedef diagonalMap::iterator                        diagonalIterator;
typedef std::pair<figureEdge, long long>             diagonalPair;
typedef std::pair<diagonalIterator,diagonalIterator> diagonalRange;

#ifdef WIN32_API
class MATH_API Convex
#else
class Convex
#endif
{
protected:
    figPoints   * m_points;
    edgeList    * m_edgeList;
    diagonalMap * m_edgeList4Search;
    edgeIterator  m_edgeIter;
    vertQueue   * m_vertQueue;
    Helper      * m_helper;
    diagonalList  m_diagonals;
    diagonalList  m_diagonalsProcessed;
    FaceFactory * m_faceFactory;
    HWND          m_hWnd;
    POINT         m_shift;
public:
    Convex(void);
    ~Convex(void);

    virtual void CreateVerticesListAndQueue();
    virtual bool CheckFigure(); //based on edges (like vectors), we have to check if we do not have any intersections, if we have we have to split figure into two or more 
                                //figures at the begining; also we have to check if the figure is close (the last point is equal to first one, but after creating edges
    virtual verticeType CheckVertexType(const figureVertice &, const figureVertice &,const figureVertice &); //Three points: prev, current, next

    virtual void HandleVertex(const figureVertice &, const figureEdge &);

    virtual const figureEdge & FindEdge(const figureVertice &, bool);

    virtual const edgeIterator & FindEdgeIter(const figureVertice &);
  
    virtual void Clean();

    void CreateEdges(const HWND &, CFigure2D *, POINT &);

    virtual bool CheckDirection(const figureVertice &, const figureVertice &); //this function returns true if the direction is counterclockwise 
protected:
    virtual void SplitFigure2Face();
    bool Check4Diagonal(const figureVertice &, figureEdge &); //the second paramter is out parameter
    void CreateFace(figureEdge &, bool);
    virtual void SetDiagonalDirection(figureEdge &);
    virtual void RemoveFromSearch(const figureEdge &);
    virtual bool GetDiagonalPrecedesor(const figureVertice &, figureEdge &);

};



//Part of code necessary to fill list and queue in set order
bool sortVertices(const figureVertice *, const figureVertice *);
bool operator < (const figureEdge &, const figureEdge &);
bool operator < (const figureVertice &, const figureVertice &);
bool operator > (const figureVertice &, const figureVertice &);